package persistence.product;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import model.Product;

public class ProductDAOPool implements ProductDAO {

    private static ProductDAOPool persistenceManager = null;
    private DataSource pool;
    private static final Logger logger = Logger.getLogger(ProductDAOJDBC.class.getName());

    private ProductDAOPool() {
    }

    public static ProductDAOPool getProductDAOPoolImplementation() {
        if (persistenceManager == null) {
            persistenceManager = new ProductDAOPool();
        }
        return persistenceManager;
    }

    @Override
    public boolean setUp(String url, String driver, String user, String password) {
        Context env = null;
        try {
            env = (Context) new InitialContext().lookup("java:comp/env");
            pool = (DataSource) env.lookup("AppbuyPool");
            if (pool == null) {
                logger.log(Level.SEVERE, "No se encontro el DataSource");
                return false;
            }
        } catch (NamingException ex) {
            logger.log(Level.SEVERE, "No se pudo abrir la conexi�n contra base de datos", ex);
            return false;
        }
        setUpMap();
        return true;
    }

    @Override
    public void setUpMap() {
        ProductDAO jDBCProductDAO = prepareForExecutingQuerry();
        if (jDBCProductDAO == null) {
            return;
        }
        jDBCProductDAO.setUpMap();
        releaseQuerryResources(jDBCProductDAO);
    }

    @Override
    public boolean createProduct(Product product) {
        ProductDAO jDBCProductDAO = prepareForExecutingQuerry();
        if (jDBCProductDAO == null) {
            return false;
        }
        boolean isExecutedOk = jDBCProductDAO.createProduct(product);
        releaseQuerryResources(jDBCProductDAO);
        return isExecutedOk;
    }

    @Override
    public boolean deleteProduct(String name) {
        ProductDAO jDBCProductDAO = prepareForExecutingQuerry();
        if (jDBCProductDAO == null) {
            return false;
        }
        boolean isExecutedOk = jDBCProductDAO.deleteProduct(name);
        releaseQuerryResources(jDBCProductDAO);
        return isExecutedOk;
    }

    @Override
    public void readProduct(String name, Map<String, Product> productArray) {
        ProductDAO jDBCProductDAO = prepareForExecutingQuerry();
        if (jDBCProductDAO == null) {
            return;
        }
        jDBCProductDAO.readProduct(name, productArray);
        releaseQuerryResources(jDBCProductDAO);
    }

    @Override
    public synchronized void readAllProducts(Map<Integer, Product> productArray, String so) {
        Iterator itr = productMap.entrySet().iterator();
        if (so == null) {
            for (int i = 1; itr.hasNext(); i++) {
                Map.Entry e = (Map.Entry) itr.next();
                productArray.put(i, (Product) e.getValue());
            }
        } else {
            String s;
            for (int i = 1; itr.hasNext();) {
                Map.Entry e = (Map.Entry) itr.next();
                s = (String) e.getKey();
                Logger.getLogger(ProductDAOPool.class.getName()).log(Level.SEVERE,
                        s);
                if (s.contains(so)) {
                    productArray.put(i, (Product) e.getValue());
                    i++;
                }
            }
        }
    }

    @Override
    public synchronized  int readPageProducts(Map<Integer, Product> productArray, String so, int pagina) {
        Iterator itr = productMap.entrySet().iterator();
        int tam = 0;
        if (so == null) {
            for (int i = 1; i < (pagina*2)-1 && itr.hasNext(); i++){
                itr.next();
            }
            for (int i = 1; i < 3 && itr.hasNext(); i++) {
                Map.Entry e = (Map.Entry) itr.next();
                productArray.put(i, (Product) e.getValue());
            }
            tam = productMap.size();
        } else {
            String s;
            for (int i = 1; i < (pagina*2)-1 && itr.hasNext(); ){
                s = (String) ((Map.Entry) itr.next()).getKey();
                if (s.contains(so)){
                    i++;
                    tam++;
                }
            }
            for (int i = 1; i < 3 && itr.hasNext(); ) {
                Map.Entry e = (Map.Entry) itr.next();
                s = (String) e.getKey();
                if (s.contains(so)) {
                    productArray.put(i, (Product) e.getValue());
                    i++;
                    tam++;
                }
            }
        }
        return tam;
    }

    @Override
    public boolean updateProduct(String name, Product product) {
        ProductDAO jDBCProductDAO = prepareForExecutingQuerry();
        if (jDBCProductDAO == null) {
            return false;
        }
        boolean isExecutedOk = jDBCProductDAO.updateProduct(name, product);
        releaseQuerryResources(jDBCProductDAO);
        return isExecutedOk;
    }

    @Override
    public boolean disconnect() {
        return true;
    }

    private ProductDAO prepareForExecutingQuerry() {
        ProductDAOJDBC jDBCpersistenceManager = new ProductDAOJDBC();
        Connection connection;
        try {
            connection = pool.getConnection();
        } catch (SQLException ex) {
            logger.log(Level.SEVERE, "No se pudo abrir la conexion contra la base de datos", ex);
            return null;
        }
        jDBCpersistenceManager.setConnection(connection);
        return jDBCpersistenceManager;
    }

    private void releaseQuerryResources(ProductDAO productDAO) {
        productDAO.disconnect();
    }
}
